import 'dart:convert';
import 'dart:io';

import 'package:base_lib/common/bloc/base_bloc.dart';
import 'package:base_lib/common/index.dart';
import 'package:base_lib/index.dart';
import 'package:common_lib/common_compoent.dart';
import 'package:common_lib/patient_management/patient_list/patient_list_entity.dart'
    as PatientBean;
import 'package:doctor_login_lib/cache/userinfo_cache.dart';
import 'package:doctor_login_lib/login/entity/doctor_login_entity.dart';
import 'package:doctor_prescribe_lib/repository/http.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:rxdart/rxdart.dart';
import '../../diagnostic_result/entity/diagnostic_result_list_entity.dart'
    as DiagnosticBean;
import '../../doctor_prescribe_component.dart';
import 'package:doctor_prescribe_lib/offline/basic_info/entity/offline_rp_entity.dart'
    as OfflineRpBean;

///线下处方基本信息
class OfflineBasicInfoBloc extends BaseBloc {
  static BasicInfoData basicInfoData;

  PublishSubject<PatientBean.Datum> patientSubject = PublishSubject();
  PatientBean.Datum _patient;

  PublishSubject<AddressResult> addressResultSubject = PublishSubject();
  AddressResult _addressResult;

  PublishSubject<String> detailAddressSubject = PublishSubject();
  String _detailAddress;

  List<DiagnosticBean.Data> _diagnosticResult = [];

  var patientEventHandler;

  SicknessResult _sicknessResult;

  String longitude;
  String latitude;

  OfflineRpBean.OfflineRpEntity offlineRp;

  int rxType;
  int medicineFormID;
  int rpInquiryID;
  var talkInfo;
  DoctorUser _doctorUser;

  void doInit(int rxType, int medicineFormID, {int rpInquiryID, talkInfo}) {
    this.rxType = rxType;
    this.medicineFormID = medicineFormID;
    this.rpInquiryID = rpInquiryID;
    this.talkInfo = talkInfo;
  }

  @override
  initState() async {
    _doctorUser = await UserInfoCache.getInstance().get();

    patientEventHandler = (context, parameters) {
      var objStr = json.encode(parameters.getObj('patientInfo'));
      FLog(objStr);
      _patient = PatientBean.Datum.fromJson(json.decode(objStr));
      patientSubject?.add(_patient);
      return;
    };
    EventBus.instance
        .register(CommonBusName.selectedPatient, patientEventHandler);
  }

  @override
  void dispose() {
    basicInfoData = null;
    EventBus.instance
        .unregister(CommonBusName.selectedPatient, patientEventHandler);
    patientSubject?.close();
    addressResultSubject?.close();
    detailAddressSubject?.close();
  }

  setAddressResult(AddressResult addressResult) {
    _addressResult = addressResult;
    addressResultSubject.add(_addressResult);
  }

  setDetailAddress(String val) {
    _detailAddress = val;
    detailAddressSubject.add(_detailAddress);
  }

  setDiagnosticResult(List<DiagnosticBean.Data> val) {
    _diagnosticResult
      ..clear()
      ..addAll(val);
  }

  setSicknessInfo(SicknessResult result) {
    _sicknessResult = result;
  }

  void addPatient(BuildContext context) {
    Routers.navigateTo(context, CommonComponent.patientManagement,
        parameters: Parameters()..putString('title', '添加就诊人'));
  }

  Future<ResultBody> savePatient(
      context, int inquiryID, int personID, PatientBean.Datum patient) {
    String personPatientInfo = json.encode(
      Map()
        ..['personID'] = personID
        ..['familyKeyID'] = personID
        ..['patientName'] = patient.patientName
        ..['patientPhone'] = patient.phone
        ..['sex'] = patient.sex
        ..['age'] = int.parse(DateUtil.returnAgeByBirthday(
            DateUtil.getDateTime(patient.birthDay)))
        ..['birthDay'] = patient.birthDay
        ..['provinceCode'] = patient.provinceCode
        ..['cityCode'] = patient.cityCode
        ..['areaCode'] = patient.areaCode
        ..['province'] = patient.province
        ..['city'] = patient.city
        ..['area'] = patient.area
        ..['address'] = patient.address
        ..['idNumber'] = patient.idCard
        ..['isSelf'] = 0
        ..['latitude'] = patient.latitude
        ..['longitude'] = patient.longitude
        ..['sawDoctor'] = 1
        ..['illDesc'] = ''
        ..['historyOfAllergy'] = patient.historyOfAllergy
        ..['allergyDetail'] = patient.allergyDetail
        ..['historyOfSickness'] = patient.historyOfSickness
        ..['sicknessDetail'] = patient.sicknessDetail
        ..['liver'] = patient.liver
        ..['renal'] = patient.renal
        ..['pregnancy'] = patient.pregnancy,
    );
    return PrescribeHttp.savePatient(inquiryID, personPatientInfo);
  }

  Future<ResultBody> getGeo(context) async {
    var key = "f778c5056f3e7ff641dab8211a051c6b";
    String url = "https://restapi.amap.com/v3/geocode/geo?output=json&key=" +
        key +
        "&address=" +
        _addressResult.provinceName +
        _addressResult.cityName +
        _addressResult.areaName +
        _detailAddress;

    var httpClient = new HttpClient();
    var data;
    var error;
    var request = await httpClient.getUrl(Uri.parse(url));
    var response = await request.close();
    if (response.statusCode == HttpStatus.ok) {
      var json = await response.transform(utf8.decoder).join();
      var temp = jsonDecode(json);
      var tempList = temp['geocodes'] as List;
      try {
        data = tempList.first;
        var location = data['location'].toString().split(',');
        longitude = location[0];
        latitude = location[1];

        offlineRp = OfflineRpBean.OfflineRpEntity(
            rp: OfflineRpBean.Rp(
                clientID: "19100717375019793291301001",
                // 处方类别ID
                rpTypeID: rxType,
                rpTypeName: rxType == 0 ? "西药" : '中药',
                clientType: 0,
                rpSource: 2,
                patientID: '',
                medicineFormID: medicineFormID,
                patientName: _patient.patientName,
                // 药品供应商名称
                providerName: "",
                doctorOrgType: 2,
                doctorOrgID: _doctorUser.orgID,
                sectionCode: _doctorUser.doctorInfo.sectionCode,
                section: _doctorUser.doctorInfo.sectionName,
                doctorID: _doctorUser.keyID,
                doctorName: _doctorUser.doctorName,
                // 初步诊断
                primaryDiagnosis: _diagnosticResult
                    .map((e) => e.hisParaValue)
                    .toList()
                    .join(','),
                primaryDiagnosisNo: _diagnosticResult
                    .map((e) => e.hisParaCode)
                    .toList()
                    .join(','),
                // 总剂
                totalDoses: 0,
                // 医嘱
                enjoin: "",
                // 费别
                feeType: 1,
                // 处方总价
                recipeAllPrice: 0,
                rpStatus: "1",
                addUser: _doctorUser.doctorName,
                chineseMedicine: OfflineRpBean.ChineseMedicine(
                    frequence: 0, everyDose: 0, direction: '')),
            patientInfo: OfflineRpBean.PatientInfo(
                patientName: _patient.patientName,
                patientSex: _patient.sex,
                patientAge: int.parse(DateUtil.returnAgeByBirthday(
                    DateUtil.getDateTime(_patient.birthDay))),
                crowd: "",
                patientPhone: _patient.phone,
                patientIdNo: _patient.patientIdNumber,
                birthDay: _patient.birthDay,
                // 监护人姓名
                guardianName: "",
                guardianIdcardNum: "",
                // 病情描述
                illDesc: "",
                // 过敏史
                historyOfAllergy: _sicknessResult?.historyOfAllergy ?? '',
                //兼容中药
                // 过敏史详情
                allergyDetail: _sicknessResult?.allergyDetail ?? '',
                // 既往病史
                historyOfSickness: _sicknessResult?.historyOfSickness ?? '',
                // 既往病史详情
                sicknessDetail: _sicknessResult?.sicknessDetail ?? '',
                // 肝功能
                liver: _sicknessResult?.liver ?? '',
                // 肾功能
                renal: _sicknessResult?.renal ?? '',
                // 妊娠哺乳
                pregnancy: _sicknessResult?.pregnancy ?? '',
                // 辨病
                diseaseDiff: "",
                // 辨证
                syndromeDiff: "",
                // 患者地址
                address: _addressResult.provinceName +
                    _addressResult.cityName +
                    _addressResult.areaName +
                    _detailAddress,
                // 患者经度
                longitude: location[0],
                // 患者纬度
                latitude: location[1]));
      } catch (e) {
        data = Map<String, dynamic>();
        print(e);
      }
    } else {
      error = ResultError('获取失败', code: response.statusCode);
    }
    var result = ResultBody(response.statusCode == HttpStatus.ok,
        data: data, error: error);
    // FLog(result.toString());
    return result;
  }

  void next(BuildContext context, int rxType,
      {int inquiryID, int personID}) async {
    if (_patient == null) {
      ToastUtil.warning('请添加就诊人');
      return;
    }

    if (_addressResult == null) {
      ToastUtil.warning('请选择地址');
      return;
    }

    if (_detailAddress?.isEmpty ?? true) {
      ToastUtil.warning('请输入详细地址');
      return;
    }

    if (_diagnosticResult.isEmpty) {
      ToastUtil.warning('请添诊断结果');
      return;
    }

    if (personID != null && inquiryID != null) {
      var result = await savePatient(context, inquiryID, personID, _patient);

      if (!result.isSuccess) {
        ToastUtil.error(result.error.msg);
        return;
      }
    }

    var result = await getGeo(context);

    if (!result.isSuccess) {
      ToastUtil.error(result.error.msg);
      return;
    }
    if (offlineRp == null) {
      ToastUtil.error('初始化数据失败');
      return;
    }

    basicInfoData = BasicInfoData(
      patient: _patient,
      addressResult: _addressResult,
      detailAddress: _detailAddress,
      diagnosticResult: _diagnosticResult,
      sicknessResult: _sicknessResult,
      rxType: rxType,
      medicineFormID: medicineFormID,
      offlineRpEntity: offlineRp,
    );

    FLog(jsonEncode(offlineRp));

    Routers.navigateTo(
      context,
      rxType == 0
          ? DoctorPrescribeComponent.westPrescriptionPage
          : DoctorPrescribeComponent.chinesePrescriptionPage,
    );
  }
}

class BasicInfoData {
  PatientBean.Datum patient;
  AddressResult addressResult;
  String detailAddress;
  List<DiagnosticBean.Data> diagnosticResult;
  SicknessResult sicknessResult;
  int rxType;
  OfflineRpBean.OfflineRpEntity offlineRpEntity;

  ///问诊人id
  String personID = '';

  /// 处方问诊ID
  int rpInquiryID;

  /// 处方问诊ID
  int medicineFormID;

  BasicInfoData({
    this.patient,
    this.addressResult,
    this.detailAddress,
    this.diagnosticResult,
    this.sicknessResult,
    this.rxType,
    this.medicineFormID,
    this.rpInquiryID,
    this.personID,
    this.offlineRpEntity,
  });

  Map<String, dynamic> toJson() {
    var map = <String, dynamic>{};
    map["patient"] = patient.toJson();
    map["addressResult"] = json.encode(addressResult);
    map["detailAddress"] = detailAddress;
    if (diagnosticResult != null) {
      map["diagnosticResult"] =
          diagnosticResult.map((v) => v.toJson()).toList();
    }
    map["sicknessResult"] = json.encode(sicknessResult);
    map["rxType"] = rxType;
    map["personID"] = personID;
    map["medicineFormID"] = medicineFormID;
    map["rpInquiryID"] = rpInquiryID;
    map["offlineRpEntity"] = json.encode(offlineRpEntity);

    return map;
  }
}
